import { Spin } from "antd";
import dayjs from "dayjs";
import EChartsReact from "echarts-for-react";
import {
  forEach,
  uniqBy,
  indexOf,
  find,
  cloneDeep,
  slice,
  map,
  sortBy,
  throttle,
  concat,
  uniq,
  head,
  last,
} from "lodash";
import { eq, findIndex, debounce } from "lodash-es";
import { useEffect, useState } from "react";

import { chartShifting, setStateBackgrounColor } from "./utils";

import { useAnalysisTask } from "~/components/Visualization/store/useTaskState";
import { useSystemConfig } from "~/hooks/systemConfig/use-systemConfig-api";
import { ParamQueryInput, ParamType } from "~/modules/api-server/types";
import {
  formatDateTime,
  formatDateTimeSS,
} from "~/modules/shared/utils/common";
import { axisData, Scheduler } from "~/modules/worker/schedule";
import { useStoreRecord } from "~/modules/worker/store/use-StoreRecord";
import { useRemotePathList } from "~/modules/worker/use-remote-path";
import { ChartType, ChartItem, Chart } from "~/modules/workspace/models";
import { useWorkSpace } from "~/modules/workspace/store/use-workspace";
import eventBus from "~/utils/event";

const ChartItem2 = () => {
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const { workSpace } = useWorkSpace();
  const { analysisTask } = useAnalysisTask();
  const { has, add } = useStoreRecord();
  const [list, setData] = useState<{ [propName: string]: any }>({});
  const { loadResult } = useRemotePathList();
  // 获取系统设置超时时间
  const { load }: any = useSystemConfig();

  const [dataZoom, setDataZoom] = useState<{
    startValue: number;
    endValue: number;
  }>({
    startValue: 0,
    endValue: 0,
  });

  useEffect(() => {
    const params: ParamQueryInput[] = [];
    forEach(workSpace.splitCharts, (item: ChartItem) => {
      forEach(item.data, (m: Chart) => {
        const paramKey =
          m.paramType == ParamType.Field ? m.title : m.expression;
        params.push({
          expr: paramKey,
          type: m.paramType,
        });
      });
    });
    const getData = async () => {
      setIsLoading(true);
      const { data } = await load();
      setTimeout(data);
      await Scheduler.get({
        flightIds: analysisTask.flights,
        params: uniqBy(params, "expr"),
        has,
        add,
        loadResult,
      });
      setData(Scheduler.datas);
      setIsLoading(false);
      Scheduler.clear();
    };
    if (
      analysisTask.flights.length > 0 &&
      params.length > 0 &&
      !Scheduler.loading
    ) {
      getData();
    }
  }, [workSpace.splitCharts, workSpace.splitCharts.length]);
  // 获取状态量背景色时间段
  const [markArea, setMarkArea] = useState<any>();
  useEffect(() => {
    const stateParamData = list[workSpace.setting.stateQuantityParams];
    const state = workSpace.setting.setBgByStateQuantity;
    const stateParam = workSpace.setting.stateQuantityParams;
    setMarkArea(setStateBackgrounColor(stateParamData, state, stateParam));
  }, [
    Scheduler.datas,
    workSpace.setting.setBgByStateQuantity,
    workSpace.setting.stateQuantityParams,
  ]);

  const setDebounce = debounce((params: any) => {
    const currIndex = findIndex(
      Object.values(Scheduler.datas)[0],
      (item: any) => {
        return eq(
          dayjs(item.systime).format("YYYY-MM-DD HH:mm:ss"),
          dayjs(params[0].axisValueLabel).format("YYYY-MM-DD HH:mm:ss")
        );
      }
    );
    eventBus.emit("pagination", {
      currIndex,
    });
  }, 500);

  // 设置超时时间
  const setTimeout = (timeout: any) => {
    const settings = timeout?.setting?.data ?? [];
    const init_get_data_timeout: number =
      find(settings, (s) => {
        return s.item == "get_data_timeout";
      })?.content?.data ?? 20;
    Scheduler.timeout = init_get_data_timeout * 1000;
  };

  useEffect(() => {
    setDataZoom({
      startValue: 0,
      endValue: uniq(concat(axisData.data, axisData.offsetAxisData)).length - 1,
    });
  }, [axisData.data.length, axisData.offsetAxisData.length]);
  const legend: string[] = [];
  const series: any[] = [];
  const yAxis: any[] = [];
  let grid: any;
  forEach(workSpace.splitCharts, (item: ChartItem, index: number) => {
    const chartParamsData = cloneDeep(list);
    grid = {
      top: "80",
      right: (index - 1) * 60 + 30,
      left: "80",
    };
    // Y轴配置
    yAxis.push({
      type: "value",
      name: item.name,
      nameTruncate: {
        maxWidth: 300,
        ellipsis: "...",
      },
      nameTextStyle: {
        fontSize: 10,
        fontWeight: 540,
      },
      nameLocation: "middle",
      nameGap: index > 1 ? 10 : 25,
      position: index === 0 ? "left" : "right",
      alignTicks: true,
      offset: index > 1 ? (index - 1) * 60 : 0,
      axisLine: {
        show: true,
        lineStyle: {
          width: "2",
          color: item.data[0]?.color,
        },
      },
      axisLabel: {
        fontSize: 9,
        inside: index > 1,
        formatter: (value: any, index: number) => {
          if (value >= 1000) {
            return value / 1000 + "K";
          } else if (value >= 10000) {
            return value / 10000 + "W";
          } else {
            return value;
          }
        },
      },
      min: item.lowerLimit ? Number(item.lowerLimit) : null,
      max: item.upperLimit ? Number(item.upperLimit) : null,
    });
    forEach(item.data, (it: Chart, i: number) => {
      legend.push(it.title);
      const paramKey =
        it.paramType == ParamType.Field ? it.title : it.expression;
      const data =
        chartParamsData &&
        chartParamsData[paramKey] &&
        chartShifting(chartParamsData[paramKey], item, paramKey);
      series.push({
        name: it.title,
        data,
        yAxisIndex: index,
        markArea: workSpace.setting.setBgByStateQuantity
          ? {
              data: map(
                slice(markArea, 0, markArea?.length - 1),
                (m: string[], index) => {
                  return [
                    {
                      xAxis: m[0],
                      itemStyle: {
                        color:
                          workSpace.setting.backgroundColors[
                            (index + 1) % 2 === 0 ? 1 : 0
                          ],
                        opacity: 0.8,
                      },
                    },
                    {
                      xAxis: m[1],
                    },
                  ];
                }
              ),
            }
          : {},
        type:
          item.chartType === ChartType.LINEAREA
            ? ChartType.LINE
            : item.chartType,
        areaStyle:
          item.chartType === ChartType.LINEAREA ? { color: it.color } : null,
        lineStyle:
          item.chartType === ChartType.LINE ? { color: it.color } : null,

        itemStyle:
          item.chartType === ChartType.SCATTER ? { color: it.color } : null,

        showSymbol: false,
        large: true,
      });
    });
  });
  if (yAxis.length === 0) {
    return <div />;
  }

  const option = {
    legend: [
      {
        data: legend,
        top: "bottom",
      },
    ],
    grid,
    tooltip: {
      trigger: "axis",
      formatter(params: any) {
        setDebounce(params);
        const axisValue = params[0].axisValueLabel;
        const marker = params[0].marker;
        const seriesName = params[0].seriesName;
        const seriesValue = params[0].value[1];
        return `
                <div>${axisValue}</div>
                <div>${marker}${seriesName} ${seriesValue} </div>
            `;
      },
    },
    toolbox: {
      left: "",
      feature: {
        dataZoom: {
          yAxisIndex: "none",
          title: {
            zoom: "区域缩放",
            back: "缩放还原",
          },
        },
        restore: {
          title: "重置",
        },
      },
    },
    dataZoom: [
      {
        type: "slider",
        xAxisIndex: [0],
        show: true,
        showDetail: true,
        top: "",
        left: "90",
        right: "24",
        startValue: dataZoom.startValue,
        endValue: dataZoom.endValue,
      },
      {
        type: "select",
        xAxisIndex: 0,
      },
    ],
    xAxis: [
      {
        type: "category",
        axisLabel: {
          formatter(value: string | number | Date) {
            return dayjs(value).format("MM-DD HH:mm:ss");
          },
        },
        data: sortBy(uniq(concat(axisData.data, axisData.offsetAxisData))),
        axisTick: {
          alignWithLabel: true,
        },
        show: true,
        boundaryGap: ["1%", "1%"],
      },
    ],
    yAxis,
    series,
  };
  const emitDateRange = (data: any) => {
    eventBus.emit("dataList", data);
    eventBus.emit("chartParamsStatistics", {
      startTime: formatDateTime(data.startTime),
      endTime: formatDateTime(data.endTime),
    });
  };
  const throttleq = throttle(emitDateRange, 1500);
  const onclick = {
    dataZoom: (e: any, c: any) => {
      const startIndex: number = c.getOption().dataZoom[0].startValue;
      const endIndex: number = c.getOption().dataZoom[0].endValue;
      const times: string[] = uniq(
        concat(axisData.data, axisData.offsetAxisData)
      );
      setDataZoom({ startValue: startIndex, endValue: endIndex });
      const start = formatDateTimeSS(times[startIndex]);
      const end = formatDateTimeSS(times[endIndex]);
      const arr = sortBy([start, end]);
      const data = {
        startTime: arr[0],
        endTime: arr[1],
      };
      throttleq(data);
    },
    restore: () => {
      const n: number = 0;
      let param: any;
      forEach(Object.keys(list), (k) => {
        if (list[k].length > n) {
          param = list[k];
        }
      });

      eventBus.emit("dataList", { startTime: "", endTime: "" });
      eventBus.emit("chartParamsStatistics", {
        startTime: param && param[0] ? formatDateTime(param[0].systime) : "",
        endTime:
          param && param[param.length - 2]
            ? formatDateTime(param[param.length - 2].systime)
            : "",
      });
      setDataZoom({
        startValue: 0,
        endValue:
          uniq(concat(axisData.data, axisData.offsetAxisData)).length - 1,
      });
    },
  };

  if (series[0] && series[0]["data"] && series[0]["data"].length > 0) {
    eventBus.emit("chartParamsStatistics", {
      startTime: formatDateTime(head(head(series[0]["data"]))),
      endTime: head(last(series[0]["data"]))
        ? formatDateTime(head(last(series[0]["data"])))
        : formatDateTime(head(series[0]["data"][series[0]["data"].length - 2])),
    });
  }
  eventBus.emit("dataList", { startTime: "", endTime: "" });

  return (
    <div id="ChartList" className="p-4">
      <Spin tip="Loading..." spinning={isLoading}>
        <EChartsReact
          option={option}
          notMerge
          lazyUpdate
          style={{ height: "500px" }}
          onEvents={onclick}
        />
      </Spin>
    </div>
  );
};

export default ChartItem2;
